package com.MoveEat.Utils;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.LinkedList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.entity.BufferedHttpEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import android.content.res.Resources;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.widget.ImageView;

public class SimplePhotoCache {

	private static final int MAX_DEFAULT = 20;

	private Drawable mDefaultPhoto = null;

	private HashMap<String, BitmapDrawable> cache;
	private LinkedList<AsyncTask<Void, Void, BitmapDrawable>> tasks;
	private HashMap<ImageView, AsyncTask<Void, Void, BitmapDrawable>> imgLinks;
	private int maxSize = MAX_DEFAULT;
	private boolean mIgnoreSSL = false;

	private boolean mCleared = false;

	public SimplePhotoCache() {
		this(null);
	}

	public SimplePhotoCache(Drawable defaultPhoto) {
		this(defaultPhoto, MAX_DEFAULT);
	}

	public SimplePhotoCache(Drawable defaultPhoto, int maxSize) {
		cache = new HashMap<String, BitmapDrawable>();
		tasks = new LinkedList<AsyncTask<Void, Void, BitmapDrawable>>();
		imgLinks = new HashMap<ImageView, AsyncTask<Void, Void, BitmapDrawable>>();
		mDefaultPhoto = defaultPhoto;
		this.maxSize = maxSize;
	}

	public void loadPhoto(final String url, final ImageView view) {
		if (mCleared) {
			return;
		}
		BitmapDrawable d = null;
		synchronized (cache) {

			d = cache.get(url);
			if (d==null){
//				Utils.log("draw is not in cache");
			}
		}
		if ((d != null) && (d.getBitmap() != null) && (!d.getBitmap().isRecycled())) {
			if (view != null) {
				synchronized (cache) {
					view.setImageDrawable(cache.get(url));
				}
				view.invalidate();
				view.requestLayout();
			}
		} else {
			AsyncTask<Void, Void, BitmapDrawable> task = new AsyncTask<Void, Void, BitmapDrawable>() {

				private BitmapDrawable d = null;

				@Override
				protected void onPreExecute() {
					synchronized (cache) {
						d = cache.get(url);

					}
				}

				@Override
				protected BitmapDrawable doInBackground(Void... params) {
					if ((d == null) || (d.getBitmap() == null)
							|| ((d.getBitmap() != null) && (d.getBitmap().isRecycled()))) {
						Resources res = Resources.getSystem();
						if (view != null) {
							res = view.getResources();
						}
						try {
							d = LoadImageFromURL(res, url, mIgnoreSSL);
						} catch (IOException e) {
							e.printStackTrace();
						}
					}

					return d;
				}

				@Override
				protected void onPostExecute(BitmapDrawable dr) {

					if (mCleared || dr == null || dr.getBitmap() == null
							|| dr.getBitmap().isRecycled()) {
						return;
					}
					synchronized (cache) {
						if (cache.size() >= maxSize) {
							cache.remove(cache.keySet().iterator().next());
						}
						cache.put(url, dr);

					}
					if (view != null) {
						if (imgLinks.get(view).equals(this)) {
							view.setImageDrawable(dr == null ? mDefaultPhoto : dr);
							view.invalidate();
							view.requestLayout();
						}
					}
					tasks.remove(this);
					if (tasks.peek() != null) {
						tasks.peek().execute();
					}
				}

			};
			imgLinks.put(view, task);
			if (tasks.size() == 0) {
				tasks.add(task);
				task.execute();
			} else {
				tasks.add(1, task);
			}
		}
	}

	public void clear() {
		Utils.log(1,"Clearing photos");
		for (BitmapDrawable bd : cache.values()) {
			if (bd != null && bd.getBitmap() != null) {
				bd.setCallback(null);
				bd.getBitmap().recycle();
			}
		}
		cache.clear();
		mCleared = true;
	}

	public void setIgnoreSSL(boolean ignore) {
		mIgnoreSSL = ignore;
	}

	public static BitmapDrawable LoadImageFromURL(Resources res, String address) throws IOException {
		return LoadImageFromURL(res, address, false);
	}

	public static BitmapDrawable LoadImageFromURL(Resources res, String address, boolean ignoreSSL)
			throws IOException {
		InputStream is = null;
		try {
			is = downloadPictureAsStream(address, ignoreSSL);
			// GlobalUtils.LogCA(1, "Loaded - " + address);
			BitmapDrawable d = new BitmapDrawable(res, is);
			// createFromStream(is, "src");
			// BitmapFactory.Options opts = new BitmapFactory.Options();
			// Bitmap b = BitmapFactory.decodeStream(is, null, opts);
			if (is != null) {
				is.close();
			}
			return d;
		} catch (IOException e) {
			Utils.log(0,"Unable to load image from url - " + address);
			// GlobalUtils.log(1, "Exception - " + e.getMessage());
			e.printStackTrace();
			return null;
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					throw e;
				}
			}
		}
	}

	private static InputStream downloadPictureAsStream(String url, boolean ignoreSSL)
			throws IOException {
		if (url == null) {
			throw new IOException();
		}

		HttpClient httpClient = null;
		InputStream stream = null;
		try {
			HttpParams params = new BasicHttpParams();
			// Set the timeout in milliseconds until a connection is
			// established.
			HttpConnectionParams.setConnectionTimeout(params, 5000);
			// Set the default socket timeout (SO_TIMEOUT)
			// in milliseconds which is the timeout for waiting for data.
			HttpConnectionParams.setSoTimeout(params, 10000);

			httpClient = new DefaultHttpClient(params);
			if (ignoreSSL) {
				SSLSocketFactory sf = (SSLSocketFactory) httpClient.getConnectionManager()
						.getSchemeRegistry().getScheme("https").getSocketFactory();
				sf.setHostnameVerifier(new AllowAllHostnameVerifier());
			}

			url = url.replaceAll("\\|", "%7C");
			HttpGet httpget = new HttpGet(url);

			HttpResponse response = httpClient.execute(httpget);
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				BufferedHttpEntity buff = new BufferedHttpEntity(entity);
				stream = buff.getContent();
				// image = BitmapFactory.decodeStream(stream);
			}
		} catch (IOException ex) {
			Utils.log(0,"Got IOException in downloadPictureAsStream" + ex.getMessage());
			ex.printStackTrace();
			throw ex;
		} finally {
			try {
				if (httpClient != null) {
					httpClient.getConnectionManager().shutdown();
				}
			} catch (Exception e) {
			}
		}

		return stream;
	}
}
